/**
 * Responsible for handling requests to server and updating console 
 */
GameCommand = new Class({
	
	Extends : Request.JSON, // (Implements Chain, Events, and Options)
	
	gameMove : null,
	log : null,
	console : null,
	response : null,
	options : {
		'ctrl'	 	: null, 
		'action' 	: null,
		'preAction' : null,
		'preLog' 	: null,
		'postLog'	: null,
		'request'	: null
	},
	
	/**
	 * Create new game command
	 * 
	 * @param string gameCmd
	 * @param object options
	 */
	initialize : function(gameCmd,options){
		if(!options) options = {};
		this.parent(options);
		if(gameCmd) this.setOptions(this.translateGameCmd(gameCmd));
		this.console = GameEng.getInstance().console;
	},
	
	/**
	 * Take a text command and parse it for all the information needed required to make the move+server request
	 * 
	 * @return Object 
	 */
	translateGameCmd : function(gameCmd){
		var invalidCmd = {'preLog' : '[Err #7921] Unrecognised Command Format.'};
		gameCmd = (gameCmd).toLowerCase();
		switch(true){
			case (gameCmd===command.beginGame):
				return {
					'preLog'	: 'Establishing communication with command net...',
					'postLog'	: 'successful',
					'request'	: new Hash({'c':'GameEng','a':'connectToGame'})
				};
				
			case (gameCmd===command.history):
				return {'preLog' : GameEng.getInstance().console.getHistory(true)};
				
			case command.move.test(gameCmd):
				var moveInf = GameCommand.parseMoveCmd(gameCmd);
				if(moveInf){
					var unit = Unit.getUnitById(moveInf.unitId);
					if(unit){
						return { // @todo change to class?
							'preLog' 	: gameCmd,
							'preAction' : 'move',
							'unit'		: unit,
							'direction'	: moveInf.direction,
							'request'	: new Hash({'c':'GameEng','a':'unitMove'})
						};
					}else{
						return {'preLog' : 'Unrecognised unit "#'+unitId+'"'};
					}
				}else{
					return invalidCmd;
				}
				
			case command.select.test(gameCmd):
				var unitId = GameCommand.parseSelectCmd(gameCmd);
				if(unitId){
					var unit = Unit.getUnitById(unitId);
					if(unit){
						return { // @todo change to class?
							'preLog' 	: gameCmd,
							'preAction' : 'select',
							'unit'		: unit,
						};
					}else{
						return {'preLog' : 'Unrecognised unit "#'+unitId+'"'};
					}
				}else{
					return invalidCmd;
				}
				
			case (command.hello.contains(gameCmd)):
				return {'preLog' : 'Hello Commander.'};
				
			case (command.goodbye.contains(gameCmd)):
				return {'preLog' : 'Goodbye Commander.'};
				
			case (command.swear.contains(gameCmd)):
				return {'preLog' : 'language!'};
			
			case (command.help.contains(gameCmd)):
				var help = '<h3>Supported Commands -</h3><ul class="manual">';
				var obj = this;
				manual.each(function(description,cmd){
					help += '<li>'+obj.formatHelpCmd(cmd,description)+'</li>';
				});
				help += '</ul>';
				return {'preLog' : help};
			
			case (command.chat.test(gameCmd)):
				var chat = Console.parseChatCmd(gameCmd);
				if(chat.recip && chat.msg){
					var plyr = Player.getPlayerById(g.activePlayer);
					var req = new Hash({'c':'GameEng','a':'sendMsg','msg':chat.msg});
					var recipString = '';
					if(chat.recip._type=="Player"){
						req.set('recip',chat.recip.getId());
						recipString = chat.recip.getName();
					}else{
						req.set('recipType',chat.recip); // i.e. team/all
						recipString = chat.recip;
					}
					return {
						'preLog'	: '<strong>'+plyr.getName()+' -&gt; '+recipString+':</strong> '+chat.msg,
						'preAction'	: 'chat',
						'request'	: req
					};
				}else if(chat.msg && !chat.recip){
					return {'preLog' : 'Unrecognised recipient. Message not sent.'};
				}else{
					return {'preLog' : 'Unrecognised chat command "'+gameCmd+'"'};
				}
				
			case (command.cmdHelp.test(gameCmd)):
				var parts	= gameCmd.split('--');
				var cmd 	= parts[0].trim();
				if(manual.has(cmd)){
					return {'preLog' : this.formatHelpCmd(cmd,manual.get(cmd))};
				}else{
					return {'preLog' : 'Unknown command "'+cmd+'"'};
				}
				
			default:
				return invalidCmd;
		}
	},
	
	formatHelpCmd : function(cmd,desc){
		return '<b>'+cmd+'</b><span>'+desc+'</span>';
	},
	
	/**
	 * Dispatch game command to server and output to console
	 */
	dispatch : function(){
		g = GameEng.getInstance();
		if(this.options.preLog) this.log = this.console.logCommand(this.options.preLog);
		if(this.options.preAction){
			switch(this.options.preAction){
				case 'move':
					var move = this.options.unit.translateMove(this.options.direction);
					if(!this.options.unit.isSelected()){
						g.clearSelected();
						this.options.unit.select();
					}
					var moveResult = this.options.unit.move(move.x,move.y,move.rot,true);
					if(moveResult){
						this.options.request.extend({'U':this.options.unit.getId(false), 'x':move.x, 'y':move.y, 'r':move.rot});
					}else{
						this.options.request = null;
					}
					if(g.isTurnEnd()){
						g.switchTurn();
					}
					break;
				case 'select':
					this.options.unit.select();
					break;
			}
		}
		var obj = this;
		if(this.options.request){
			this.options.request.set('B',GameEng.getInstance().battleId);
			this.options.url = 'g.php?';
			this.options.url += this.options.request.toQueryString();
			this.ajax = new Request.JSON({
				'url' : this.options.url,
				'onSuccess' : function(resp){
					obj.response = resp;
					if(obj.options.postLog) obj.log.append(obj.options.postLog);
					if(resp && resp.debug) alert("Debug: "+resp.debug);
					if(resp && resp.ts) g.timestamp = resp.ts; 
				}
			});
			g.requestQueue.addRequest(this.options.url,this.ajax);
			g.requestQueue.send(this.options.url);
		}
	}
});

/*-- GameCommand Static Methods -- */

/**
 * Parse a move command string into move details
 * @param string cmd
 * @return object
 */
GameCommand.parseMoveCmd = function(cmd){
	var parts = cmd.split(":");
	if(parts[0] && parts[1]){
		var move = new Hash({'direction':(parts[1]).trim()});
		var unitId = parts[0].split('#');
		move.extend({'unitId':(unitId[1]).trim()});
		return move;
	}else{
		return false;
	}
}

/**
 * Parse a select command to retrieve unit id
 * @param string cmd
 * @return string
 */
GameCommand.parseSelectCmd = function(cmd){
	var parts = cmd.split("#");
	if(parts[1]){
		return (parts[1]+'').trim();
	}else{
		return false;
	}
}